home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / ProcDoggie 1.0a6 / UEmergMem.inc1.p < prev    next >
Encoding:
Text File  |  1991-02-07  |  8.4 KB  |  267 lines  |  [TEXT/MPS ]

  1. {-------------------------------------------------------------------------------
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    Interfaces for the emergency memory routines
  6. #
  7. #    Program:    ProcDoggie
  8. #    File:        UEmergMem.inc1.p - Pascal Implementation
  9. #
  10. #    by:        Forrest Tanaka
  11. #
  12. #    Copyright © 1988-1991 Apple Computer, Inc.
  13. #    All rights reserved.
  14. #
  15. -------------------------------------------------------------------------------}
  16. {[j=20/57/1$] Pasmat Options}
  17. {$R-}
  18.  
  19.  
  20. (*******************************************************************************
  21. * Constants
  22. *******************************************************************************)
  23.  
  24.     CONST
  25.         kEmergMemSize = 32768; {Number of bytes of emergency memory to allocate}
  26.         kMemoryMargin = 32768; {Minimum amount of free memory I allow in the heap}
  27.  
  28.  
  29. (*******************************************************************************
  30. * Global Variables
  31. *******************************************************************************)
  32.  
  33.     VAR
  34.         gEmergMem: Handle; {Handle to block of emergency memory}
  35.  
  36.  
  37. {$S Main}
  38. (*******************************************************************************
  39. * Private: AppGrowZone - Custom grow-zone procedure
  40. *
  41. * This is a very basic grow zone procedure.  My application keeps a reserve
  42. * handle of memory in case the Memory Manager gets a request for some memory
  43. * that is not available in my heap.  If memory were to get tight (<32k), the
  44. * Toolbox will crash the system.  This grow-zone proc tries to thwart that
  45. * possibility by releasing the 32K block of emergency memory if it hasn’t been
  46. * released already and if the amount of memory requested is less than 32K.
  47. * Hopefully, that’s enough to satisfy the memory request.
  48. *
  49. * There are three conditions in which the emergency memory isn’t freed.  If the
  50. * emergency memory is already free, obviously there isn’t much that can be done.
  51. * If the emergency memory is equal to GZSaveHnd, then it was the reallocation of
  52. * emergency memory that caused this grow-zone proc to be called.  So it doesn’t
  53. * make much sense to free it in that case.  If the size of the memory request is
  54. * more than the size of emergency memory, then I don’t bother to free emergency
  55. * memory because I assume that the toolbox handles such huge requests for memory
  56. * properly.  Warning: that isn’t always a good assumption, but that’s not my
  57. * fault.
  58. *
  59. *     WARNING: Register A5 might not be valid when grow-zone procedures
  60. *     are called. Read Technical Note #136 and 208.
  61. *
  62. * The "cbNeeded" parameter is the number of bytes that the Memory Manager needs
  63. * to fulfill the memory request it had received.  The number of bytes actually
  64. * freed by AppGrowZone is returned.
  65. *******************************************************************************)
  66.  
  67.  
  68.     FUNCTION AppGrowZone (cbNeeded: Size): LongInt;
  69.  
  70.         VAR
  71.             theA5: LongInt; {Value of A5 when AppGrowZone is called}
  72.  
  73.     BEGIN
  74.         (* Remember the current value of A5 *)
  75.         theA5 := SetCurrentA5;
  76.  
  77.         (* Free emergency memory if possible *)
  78.         IF (gEmergMem^ <> NIL) & (gEmergMem <> GZSaveHnd) & (cbNeeded <=
  79.                 kEmergMemSize) THEN
  80.             BEGIN
  81.                 EmptyHandle (gEmergMem);
  82.                 AppGrowZone := kEmergMemSize
  83.             END
  84.         ELSE
  85.             AppGrowZone := 0;
  86.  
  87.         (* Restore A5 *)
  88.         theA5 := SetA5 (theA5)
  89.     END;
  90.  
  91.  
  92. {$S Main}
  93. (*******************************************************************************
  94. * Public: ConnectAppGZ
  95. *
  96. * It’s pretty self-explanatory.
  97. *******************************************************************************)
  98.  
  99.     PROCEDURE ConnectAppGZ;
  100.  
  101.     BEGIN
  102.         SetGrowZone (@AppGrowZone)
  103.     END;
  104.  
  105.  
  106. {$S Main}
  107. (*******************************************************************************
  108. * Public: DisconnectAppGZ
  109. *
  110. * It’s pretty self-explanatory.
  111. *******************************************************************************)
  112.  
  113.     PROCEDURE DisconnectAppGZ;
  114.  
  115.     BEGIN
  116.         SetGrowZone (NIL)
  117.     END;
  118.  
  119.  
  120. {$S %A5Init}
  121. (*******************************************************************************
  122. * Public: InitEmergMem
  123. *
  124. * It’s pretty self-explanatory.
  125. *******************************************************************************)
  126.  
  127.     PROCEDURE InitEmergMem;
  128.  
  129.     BEGIN
  130.         gEmergMem := NewHandle (kEmergMemSize);
  131.         ConnectAppGZ
  132.     END;
  133.  
  134.  
  135. {$S Main}
  136. (*******************************************************************************
  137. * Public: NoEmergMem
  138. *
  139. * We check on the handle and the master pointer of gEmergMem to see if the
  140. * emergency memory block has been emptied by AppGrowZone, or was never allocated
  141. * in the first place.
  142. *******************************************************************************)
  143.  
  144.     FUNCTION NoEmergMem: Boolean;
  145.  
  146.     BEGIN
  147.         (* Empty handle means no emergency memory *)
  148.         NoEmergMem := (gEmergMem = NIL) | (gEmergMem^ = NIL)
  149.     END;
  150.  
  151.  
  152. {$S Main}
  153. (*******************************************************************************
  154. * Public: RecoverEmergMem
  155. *
  156. * Not much to describe.
  157. *******************************************************************************)
  158.  
  159.     PROCEDURE RecoverEmergMem;
  160.  
  161.     BEGIN
  162.         ReallocHandle (gEmergMem, kEmergMemSize);
  163.     END;
  164.  
  165.  
  166. {$S Main}
  167. (*******************************************************************************
  168. * Public: FailLowMemory
  169. *
  170. * PurgeSpace is used to determine how much free memory there’d be in the heap if
  171. * all purgeable blocks were purged.  If this amount is less than the amount
  172. * needed, or if there isn’t any emergency memory, TRUE is returned.
  173. *******************************************************************************)
  174.  
  175.     FUNCTION FailLowMemory (memRequest: LongInt): Boolean;
  176.  
  177.     VAR
  178.         total:  LongInt; {Total amount of free memory if heap was purged}
  179.         contig: LongInt; {Max amount of free contiguous memory if heap was purged}
  180.  
  181.     BEGIN
  182.         PurgeSpace ((*<*)total, (*<*)contig);
  183.         FailLowMemory := (total < (memRequest + kMemoryMargin)) | NoEmergMem
  184.     END;
  185.  
  186.  
  187. {$S Main}
  188. (*******************************************************************************
  189. * Public: NewHandleMargin
  190. *
  191. * I don’t call SysError with an ID 25 if there isn’t enough memory to satisfy
  192. * the request, so there isn’t much reason to use the grow-zone proc.  So, I
  193. * disconnect the grow-zone proc temporarily just before I allocate the memory.
  194. *******************************************************************************)
  195.  
  196.     FUNCTION NewHandleMargin (requestedSize: Size;
  197.                               appHeapAlloc:  Boolean;
  198.                               clearMem:      Boolean): Handle;
  199.  
  200.         VAR
  201.             total:  LongInt; {Total free bytes after a theoretical heap purge/compaction}
  202.             contig: LongInt; {Largest contig free block from theoretical heap purge/compaction}
  203.  
  204.     BEGIN
  205.         IF FailLowMemory (requestedSize) THEN
  206.             NewHandleMargin := NIL
  207.         ELSE
  208.             BEGIN
  209.                 (* We handle memFullErr properly, so don’t need grow-zone proc *)
  210.                 DisconnectAppGZ;
  211.  
  212.                 (* Allocate the memory with the requested options *)
  213.                 IF (NOT appHeapAlloc) AND clearMem THEN
  214.                     NewHandleMargin := NewHandleSysClear (requestedSize)
  215.                 ELSE IF (NOT appHeapAlloc) THEN
  216.                     NewHandleMargin := NewHandleSys (requestedSize)
  217.                 ELSE IF clearMem THEN
  218.                     NewHandleMargin := NewHandleClear (requestedSize)
  219.                 ELSE
  220.                     NewHandleMargin := NewHandle (requestedSize);
  221.  
  222.                 (* Connect up the grow-zone proc again *)
  223.                 ConnectAppGZ
  224.             END
  225.     END;
  226.  
  227.  
  228. {$S Main}
  229. (*******************************************************************************
  230. * Public: NewPtrMargin
  231. *
  232. * I don’t call SysError with an ID 25 if there isn’t enough memory to satisfy
  233. * the request, so there isn’t much reason to use the grow-zone proc.  So, I
  234. * disconnect the grow-zone proc temporarily just before I allocate the memory.
  235. *******************************************************************************)
  236.  
  237.     FUNCTION NewPtrMargin (requestedSize: Size;
  238.                            appHeapAlloc:  Boolean;
  239.                            clearMem:      Boolean): Ptr;
  240.  
  241.         VAR
  242.             total:  LongInt; {Total free bytes after a theoretical heap purge/compaction}
  243.             contig: LongInt; {Largest contig free block from theoretical heap purge/compaction}
  244.  
  245.     BEGIN
  246.         IF FailLowMemory (requestedSize) THEN
  247.             NewPtrMargin := NIL
  248.         ELSE
  249.             BEGIN
  250.                 (* We handle memFullErr properly, so don’t need grow-zone proc *)
  251.                 DisconnectAppGZ;
  252.  
  253.                 (* Allocate the memory with the requested options *)
  254.                 IF (NOT appHeapAlloc) AND clearMem THEN
  255.                     NewPtrMargin := NewPtrSysClear (requestedSize)
  256.                 ELSE IF NOT appHeapAlloc THEN
  257.                     NewPtrMargin := NewPtrSys (requestedSize)
  258.                 ELSE IF clearMem THEN
  259.                     NewPtrMargin := NewPtrClear (requestedSize)
  260.                 ELSE
  261.                     NewPtrMargin := NewPtr (requestedSize);
  262.  
  263.                 (* Connect up the grow-zone proc again *)
  264.                 ConnectAppGZ
  265.             END
  266.     END;
  267.